package com.lujianfei.imagesearch.model;

import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Random;
import java.util.Set;

import com.lujianfei.imagesearch.Constants;
import com.lujianfei.imagesearch.utils.Convolution;
import com.lujianfei.imagesearch.utils.Utils;

public class MainModel {

	/**
	 * 滤波算法
	 * @see https://blog.csdn.net/fastbox/article/details/7984721
	 * @param image
	 * @param type
	 */
	public void filter(BufferedImage image,int type) {
		double[][] kernelData = new double[][] { 
		    { 1f / 9f, 1f / 9f, 1f / 9f }, 
		    { 1f / 9f, 1f / 9f, 1f / 9f },
			{ 1f / 9f, 1f / 9f, 1f / 9f }, };
			
		Convolution conR = new Convolution.Builder()
				.setKernel(3, 3)
				.setImage(image.getHeight(), image.getWidth(), 1, 0)
				.create();
	
		conR.fillInKernel(kernelData);
		
		Convolution conG = new Convolution.Builder()
				.setKernel(3, 3)
				.setImage(image.getHeight(), image.getWidth(), 1, 0)
				.create();
		conG.fillInKernel(kernelData);
		
		Convolution conB = new Convolution.Builder()
				.setKernel(3, 3)
				.setImage(image.getHeight(), image.getWidth(), 1, 0)
				.create();
		
		conB.fillInKernel(kernelData);

		double[][] imageDataR = new double[image.getHeight()][image.getWidth()];
		double[][] imageDataG = new double[image.getHeight()][image.getWidth()];
		double[][] imageDataB = new double[image.getHeight()][image.getWidth()];
		for (int i = 0; i < image.getHeight(); i++) {
			for (int j = 0; j < image.getWidth(); j++) {
				int rgb = image.getRGB(j, i);
				final int r = (rgb >> 16) & 0xff;
				final int g = (rgb >> 8) & 0xff;
				final int b = rgb & 0xff;
				imageDataR[i][j] = r;
				imageDataG[i][j] = g;
				imageDataB[i][j] = b;
			}
		}
		conR.fillInImage(imageDataR);
		conR.operation(type);
		conR.fillOutImage(imageDataR);
		
		conG.fillInImage(imageDataG);
		conG.operation(type);
		conG.fillOutImage(imageDataG);
		
		conB.fillInImage(imageDataB);
		conB.operation(type);
		conB.fillOutImage(imageDataB);
		for (int i = 0; i < image.getHeight(); i++) {
			for (int j = 0; j < image.getWidth(); j++) {
				int r = Utils.clamp((int)imageDataR[i][j]);
				int g = Utils.clamp((int)imageDataG[i][j]);
				int b = Utils.clamp((int)imageDataB[i][j]);
				image.setRGB(j, i, Utils.colorToRGB(0, r, g, b));
			}
		}
	}

	public void addNoise(BufferedImage image, int type) {
		Random random = new Random();
		Set<Integer> set = new HashSet<>();
		for (int i = 0; i < image.getWidth(); i++) {
			for (int j = 0; j < image.getHeight(); j++) {
				int randomX = random.nextInt(image.getWidth());
				int randomY = random.nextInt(image.getHeight());
				int newColor = 0;
				switch (type) {
				case Constants.NOISE_MODE.PEPPER_SALT_NOISE: {
					newColor = (random.nextInt(2) + 1) % 2 == 0 ? 0 : 255;
				}
					break;
				case Constants.NOISE_MODE.PEPPER_NOISE: {
					newColor = 0;
				}
					break;
				case Constants.NOISE_MODE.SALT_NOISE: {
					newColor = 255;
				}
					break;

				default:
					break;
				}
				int key = randomX + randomY; // 去重处理
				if (!set.contains(key)) {
					image.setRGB(randomX, randomY, Utils.colorToRGB(0, newColor, newColor, newColor));
					set.add(key);
				}
			}
		}
	}

	public void addGray(BufferedImage image, int type) {
		// TODO Auto-generated method stub
		for (int i = 0; i < image.getWidth(); i++) {
			for (int j = 0; j < image.getHeight(); j++) {
				int color = image.getRGB(i, j);
				final int r = (color >> 16) & 0xff;
				final int g = (color >> 8) & 0xff;
				final int b = color & 0xff;
				int gray = 0;
				switch (type) {
				case Constants.GRAY_MODE.MAX: {
					gray = Utils.getBigger(r, g, b);
				}
					break;
				case Constants.GRAY_MODE.MIN: {
					gray = Utils.getSmall(r, g, b);
				}
					break;
				case Constants.GRAY_MODE.AVE: {
					gray = Utils.getAvg(r, g, b);
				}
					break;
				case Constants.GRAY_MODE.WEIGHT: {
					gray = (int) (0.3 * r + 0.59 * g + 0.11 * b);// 加权法灰度化
				}
					break;
				}
				image.setRGB(i, j, Utils.colorToRGB(0, gray, gray, gray));
			}
		}
	}

}
